/*-------------------------------------------------------------------------
DriverGen.cs -- Generation of the Compiler Driver
Compiler Generator Coco/R,
Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
extended by M. Loeberbauer & A. Woess, Univ. of Linz
extended (June 2004) by Pat Terry, Rhodes University (p.terry@ru.ac.za)
(changes marked as "pdt")

This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

As an exception, it is allowed to write an extension of Coco/R that is
used as a plugin in non-free software.

If not otherwise stated, any source code generated by Coco/R (other than
Coco/R itself) does not fall under the GNU General Public License.
-------------------------------------------------------------------------*/
using System;
using System.IO;

namespace at.jku.ssw.Coco {

public class DriverGen {

	const int  EOF = -1;
	const char CR  = '\r';
	const char LF  = '\n';

	static FileStream fram;      // driver frame file
	static StreamWriter gen;     // generated driver source file
	static string srcName;       // name of the attributed grammar file
	static string srcDir;        // directory of attributed grammar file

	static void CopyFramePart (string stop) {
		int last = 0;
		char startCh = stop[0];
		int endOfStopString = stop.Length-1;
		int ch = fram.ReadByte();
		while (ch != EOF)
			if (ch == startCh) {
				int i = 0;
				do {
					if (i == endOfStopString) return; // stop[0..i] found
					ch = fram.ReadByte(); i++;
				} while (ch == stop[i]);
				// stop[0..i-1] found; continue with last read character
				gen.Write(stop.Substring(0, i));
			} else if (ch == LF) { if (last != CR) gen.WriteLine(); last = ch; ch = fram.ReadByte();
			} else if (ch == CR) { gen.WriteLine(); last = ch; ch = fram.ReadByte();
			} else {
				gen.Write((char)ch); last = ch; ch = fram.ReadByte();
			}
		Errors.Exception(" -- incomplete or corrupt driver frame file");
	}

	static void OpenGen(bool backUp) {
		try {
			string fn = srcDir + Tab.gramSy.name + ".cs";
			if (File.Exists(fn) && backUp) File.Copy(fn, fn + ".old", true);
			gen = new StreamWriter(new FileStream(fn, FileMode.Create));
		} catch (IOException) {
			Errors.Exception("-- Cannot create " + Tab.gramSy.name + ".cs");
		}
	}

	public static void WriteDriver() {
		string fr = srcDir + Tab.gramSy.name + ".frame";
		if (!File.Exists(fr)) {
			fr = srcDir + "Driver.frame";
			if (!File.Exists(fr)) {
				if (Tab.frameDir != null) fr = Tab.frameDir.Trim() + Path.DirectorySeparatorChar + "Driver.frame";
				if (!File.Exists(fr))
					Errors.Exception("-- Cannot find Driver.frame or " + Tab.gramSy.name + ".frame");
			}
		}
		try {
			fram = new FileStream(fr, FileMode.Open);
		} catch (FileNotFoundException) {
			Errors.Exception("-- Cannot open driver frame file");
		}
		OpenGen(true);
		CopyFramePart("-->begin");
		if (!srcName.ToLower().EndsWith("coco.atg")) {
			gen.Close(); OpenGen(false);
		}
		CopyFramePart("-->namespace");
		if (Tab.nsName != null && Tab.nsName.Length > 0) gen.Write(Tab.nsName);
		else gen.Write(Tab.gramSy.name);
		CopyFramePart("-->class"); gen.Write(Tab.gramSy.name);
		CopyFramePart("$$$");
		gen.Close();
	}

	public static void Init(string file, string dir) {
		srcName = file;
		srcDir  = dir;
	}

} // end DriverGen

} // end namespace
